package com.paper.tiger.easy.rpc.s.client.config;

import com.paper.tiger.easy.rpc.annotation.Remote;
import com.paper.tiger.easy.rpc.s.client.client.ProxyFactoty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.stereotype.Component;
import org.springframework.util.ClassUtils;

import java.util.Set;

/**
 * [简要描述]:
 * [详细描述]:
 *
 * @author ZouHaiBo
 * @version 1.0, 2021/6/28 18:12
 * @since JDK 1.8
 */
@Component
public class Lion implements BeanFactoryPostProcessor, EnvironmentAware
{
    private static Logger logger = LoggerFactory.getLogger(Lion.class);

    private Environment environment;

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
    {
        try
        {
            //            ConfigurableListableBeanFactory beanFactory = SpringContextSupport.getBeanFactory();

            String property = environment.getProperty("netty.rpc.rpcPackages");
            DefaultListableBeanFactory factory = (DefaultListableBeanFactory) beanFactory;
            String[] beanDefinitionNames = factory.getBeanDefinitionNames();
            PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
            StandardEnvironment standardEnvironment = new StandardEnvironment();

            String resourcePath = ClassUtils
                    .convertClassNameToResourcePath(standardEnvironment.resolveRequiredPlaceholders(property));

            resourcePath = "classpath*:"+resourcePath+"/**/*.class";

            Resource[] resources = resolver.getResources(resourcePath);

            CachingMetadataReaderFactory readerFactory = new CachingMetadataReaderFactory();

            out:for (Resource resource : resources)
            {
                if (resource.isReadable()){

                    MetadataReader reader = readerFactory.getMetadataReader(resource);

                    ClassMetadata cla = reader.getClassMetadata();
                    String className = cla.getClassName();
                    Class<?> aClass = Class.forName(className);
                    AnnotationMetadata metadata = reader.getAnnotationMetadata();
                    Set<String> annotationTypes = metadata.getAnnotationTypes();
                    if (annotationTypes.contains(Remote.class.getName())){


                        // 如果是自己服务的接口，不需要进行注册，查看是否有实现类
                        for (String beanDefinitionName : beanDefinitionNames)
                        {
                            AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) factory.getBeanDefinition(beanDefinitionName);
                            Class<?> beanClass = null;
                            try
                            {
                                beanClass = beanDefinition.getBeanClass();
                            }catch (Exception e){
                                continue ;
                            }
                            Class<?>[] interfaces = beanClass.getInterfaces();
                            if (interfaces != null || interfaces.length >0){
                                for (Class<?> anInterface : interfaces)
                                {
                                    if (anInterface == aClass){
                                        continue out;
                                    }
                                }
                            }

                        }

                        beanFactory.registerSingleton("rpc-"+cla.getClassName(), ProxyFactoty.newProxy(aClass));
                        logger.info("注册bean 到 工厂中,bean wei :{}",aClass);
                    }
                }
            }
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }


    @Override
    public void setEnvironment(Environment environment)
    {
        this.environment = environment;
    }
}
